
import uuid
import pandas as pd
from typing import List
import time    
from app.services.db_service_factory import get_db_service
from app.services.pubsub_service import pubsub_service
from app.core.config import settings
from app.models.database import TaskDB,DOIItemDB

db_service=get_db_service()

class DOIParser:
    @staticmethod
    def validate_doi(doi: str) -> bool:
        # 简单的DOI格式验证
        return bool(doi and '/' in doi)

    @staticmethod
    def generate_task_id() -> str:
        return str(uuid.uuid4())
     
    
    @staticmethod
    async def add_task(task_id:str,client_id: str,file_name: str, doi_list: List[str],type:str="DOI") -> str: 
        # 初始化任务状态
        task_status = {
            "task_id": task_id,
            "client_id":client_id,
            "status": "pending",
            "total_dois": len(doi_list),
            "success_dois": 0,
            "completed_dois": 0,
            "failed_dois": 0, 
            "start_time":time.strftime("%Y-%m-%d %H:%M:%S"),
            "end_time":"",
            "file_name":file_name, 
            "task_type":type
        }
        # 保存任务状态到Redis
        #redis_service.save(task_id, task_status)
        db_service.save_entity(TaskDB,task_status)
        return task_status
    
    @staticmethod
    async def update_task_status(task_id: str, status_update: dict): 
        # 获取任务的完整状态 
        #redis_service.update(task_id, status_update) 
        db_service.save_entity_by_filter(TaskDB,status_update,{"task_id":task_id})
        
        task_status = db_service.get_entity_as_dict(TaskDB,task_id)
        pattern = f"doi_task:doi_item:{task_id}:*"
        #items = redis_service.get_items_by_pattern(pattern)
        items=db_service.query_entities_as_dicts(DOIItemDB,{"task_id":task_id})

        if items:
        # 按original_index排序
           items.sort(key=lambda item: item.get("original_index", float('inf')))
           task_status["dois"] = items
       
 
        # 使用 PubSubService 发布消息
        client_id = task_status.get("client_id", "") 
        message_type="task_status_update"  if task_status["task_type"]=="DOI" else task_status["task_type"]+"_task_status_update"        
        pubsub_service.publish_message(
            client_id=client_id,
            message_type=message_type,
            task_id=task_id,
            data=task_status
        )
         
    
    @staticmethod
    async def add_doi_metater(task_id:str, doi:str, metadata: dict, send:bool=False, index:int=None): 
        key=f"doi_item:{task_id}:{doi}"
        
        # 添加索引信息到元数据中
        if index is not None:
            metadata["original_index"] = index
        
        #task_status = redis_service.get(task_id)
        task_status=db_service.get_entity_as_dict(TaskDB,task_id)
        if task_status:
            #redis_service.save(key, metadata) 
            db_service.save_entity(DOIItemDB,metadata)
            client_id = task_status.get("client_id", "")
            # 发送消息到特定任务的WebSocket
            if send:
                message_type="metadata_status_update"  if task_status["task_type"]=="DOI" else task_status["task_type"]+"_metadata_status_update"                 
                pubsub_service.publish_message(
                client_id=client_id,
                message_type=message_type,
                task_id=task_id,
                data=metadata
            )
             

    @staticmethod
    async def update_doi_metater(task_id:str,doi:str,status_update: dict): 
        key=f"doi_item:{task_id}:{doi}"
        #task_status = redis_service.get(task_id)
        task_status=db_service.get_entity_as_dict(TaskDB,task_id)
        if task_status: 
            #redis_service.update(key,status_update) 
            db_service.save_entity_by_filter(DOIItemDB,status_update,{"task_id":task_id,"doi":doi})
            #metadata=redis_service.get(key)
            metadatas=db_service.query_entities_as_dicts(DOIItemDB,{"task_id":task_id,"doi":doi})
            if metadatas and len(metadatas)>0:
                metadata=metadatas[0]
                client_id = task_status.get("client_id", "")
                message_type="metadata_status_update"  if task_status["task_type"]=="DOI" else task_status["task_type"]+"_metadata_status_update"                
                pubsub_service.publish_message(
                client_id=client_id,
                message_type=message_type,
                task_id=task_id,
                data=metadata
                )
         
    @staticmethod
    async def add_jiangsu_metaer(task_id:str,metadata: dict, send:bool=False, index:int=None)->DOIItemDB: 
      try:          
        # 添加索引信息到元数据中
        if index is not None:
            metadata["original_index"] = index 
        task_status=db_service.get_entity_as_dict(TaskDB,task_id)
        
        if task_status: 
            
            entity= db_service.save_entity(DOIItemDB,metadata)
          
            client_id = task_status.get("client_id", "")
            # 发送消息到特定任务的WebSocket
            if send:
                message_type="metadata_status_update"  if task_status["task_type"]=="DOI" else task_status["task_type"]+"_metadata_status_update"
                pubsub_service.publish_message(
                client_id=client_id,
                message_type=message_type,
                task_id=task_id,
                data=metadata
            ) 
            return entity
        
      except Exception as e:
          print(str(e))
          
    @staticmethod
    async def add_jiangsu_metaer_list(task_id:str,metadata_list: List[dict], send:bool=False)->DOIItemDB: 
      try:          
        # 添加索引信息到元数据中 
        task_status=db_service.get_entity_as_dict(TaskDB,task_id)
        
        if task_status: 
            
            entities= db_service.save_entities(DOIItemDB,metadata_list)
          
            client_id = task_status.get("client_id", "")
            # 发送消息到特定任务的WebSocket
            if send:
                message_type="metadata_list_status_update"  if task_status["task_type"]=="DOI" else task_status["task_type"]+"_metadata_list_status_update"
                pubsub_service.publish_message(
                client_id=client_id,
                message_type=message_type,
                task_id=task_id,
                data=metadata_list
            ) 
            return entities
        
      except Exception as e:
          print(str(e))
         
    @staticmethod
    async def update_jiangsu_metater(task_id:str,item_id:int,status_update: dict):  
        task_status=db_service.get_entity_as_dict(TaskDB,task_id)
        if task_status:  
            db_service.save_entity_by_filter(DOIItemDB,status_update,{"task_id":task_id,"id":item_id}) 
            metadatas=db_service.query_entities_as_dicts(DOIItemDB,{"task_id":task_id,"id":item_id})
            if metadatas and len(metadatas)>0:
                metadata=metadatas[0]
                client_id = task_status.get("client_id", "")
                
                message_type="metadata_status_update"  if task_status["task_type"]=="DOI" else task_status["task_type"]+"_metadata_status_update"                

                pubsub_service.publish_message(
                client_id=client_id,
                message_type=message_type,
                task_id=task_id,
                data=metadata
                )         

    # 处理文件内容的方法
    @staticmethod
    def parse_txt_content(content: bytes) -> List[str]:
        # 解码内容
        text = content.decode('utf-8')
        # 按行分割并移除空白字符
        dois = [line.strip() for line in text.splitlines()]
        # 过滤掉空行
        return [doi for doi in dois if doi]
    
    @staticmethod
    def parse_excel_content(content: bytes) -> List[str]:
        try:
            # 使用BytesIO包装字节对象
            import io
            excel_data = io.BytesIO(content)
            # 使用pandas从内存中读取Excel
            df = pd.read_excel(excel_data)
            # 查找包含'doi'的列名（不区分大小写）
            doi_columns = [col for col in df.columns if 'doi' in col.lower()]
            if not doi_columns:
                raise ValueError("未找到DOI列")
            # 使用第一个匹配的DOI列
            doi_column = doi_columns[0]
            # 提取DOI并移除空值
            dois = df[doi_column].dropna().astype(str).tolist()
            # 清理DOI（移除空白字符）
            return [doi.strip() for doi in dois]
        except Exception as e:
            raise ValueError(f"解析Excel文件失败: {str(e)}")
    
    @classmethod
    def process_file_content(cls, content: bytes, file_type: str) -> List[str]:
        if file_type == 'txt': 
            dois = cls.parse_txt_content(content) 
            return dois
        elif file_type in ['xlsx', 'xls']:
            dois = cls.parse_excel_content(content)
            return dois
        else:
            raise ValueError(f"不支持的文件类型: {file_type}")
 
 
    
  
     